package com.laxcen.basiclib.engine;

import android.Manifest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import com.laxcen.basiclib.BaseApp;
import com.laxcen.basiclib.R;
import com.laxcen.basiclib.core.bridgewebview.bean.AjaxData;
import com.laxcen.basiclib.core.bridgewebview.bean.AjaxParam;
import com.laxcen.basiclib.core.bridgewebview.bean.H5AppConfig;
import com.laxcen.basiclib.core.bridgewebview.bean.PushLog;
import com.laxcen.basiclib.core.bridgewebview.bean.SystemConst;
import com.laxcen.basiclib.core.bridgewebview.bean.WinParam;
import com.laxcen.basiclib.core.broadcast.BroadcastManager;
import com.laxcen.basiclib.core.crashpush.CrashPushManager;
import com.laxcen.basiclib.core.download.DownloadCallback;
import com.laxcen.basiclib.core.download.DownloadInfo;
import com.laxcen.basiclib.core.download.DownloadManager;
import com.laxcen.basiclib.core.http.HttpManager;
import com.laxcen.basiclib.core.http.callback.StringCallback;
import com.laxcen.basiclib.core.http.request.RequestCall;
import com.laxcen.basiclib.core.location.LocationHelper;
import com.laxcen.basiclib.core.location.LocationInfo;
import com.laxcen.basiclib.core.permission.PermissionManager;
import com.laxcen.basiclib.core.record.AudioCallback;
import com.laxcen.basiclib.core.record.AudioRecordManager;
import com.laxcen.basiclib.core.task.Task;
import com.laxcen.basiclib.core.task.TaskManager;
import com.laxcen.basiclib.core.update.Update;
import com.laxcen.basiclib.core.update.utils.UpdateUtils;
import com.laxcen.basiclib.engine.callback.AjaxCallback;
import com.laxcen.basiclib.engine.callback.EventDataListener;
import com.laxcen.basiclib.engine.callback.OnPhotoResult;
import com.laxcen.basiclib.engine.callback.OnResult;
import com.laxcen.basiclib.service.MqttService;
import com.laxcen.basiclib.ui.activity.WebActivity;
import com.laxcen.basiclib.utils.ActivityCollectorUtil;
import com.laxcen.basiclib.utils.CommonUtil;
import com.laxcen.basiclib.utils.FileUtil;
import com.laxcen.basiclib.utils.FingerprintUtil;
import com.laxcen.basiclib.utils.JsonUtil;
import com.laxcen.basiclib.utils.LogUtil;
import com.laxcen.basiclib.utils.SharedPreferencesUtil;
import com.laxcen.basiclib.utils.ToastUtil;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import okhttp3.Call;
import okhttp3.Request;

import static android.app.Activity.RESULT_OK;
import static com.laxcen.basiclib.service.MqttService.MQTT_MESSAGE_LISTENER;

/**
 *  综合API 实现
 */
public class ApiEngine {
    private WeakReference<Activity> activity;
    //设置当前页是否可以直接返回桌面
    public boolean canBackToMain = false;
    public static H5AppConfig h5AppConfig;
    public ApiEngine(Activity activity){
        this.activity = new WeakReference<>(activity);
    }
    public static ApiEngine bind(Activity activity){
        ApiEngine apiEngine =  new ApiEngine(activity);
        apiEngine.init();
        return apiEngine;
    }
    private void init(){
        //启动mqtt
        MqttService.actionStart(activity.get());
        EventBus.getDefault().register(this);
        loadH5Config(false);
    }

    /**
     *  加载H5的配置信息
     */
    public void loadH5Config(boolean reload){
        CommonUtil.loadConfig(activity.get(),reload);
    }
    //取消绑定
    public void unBind(){
        if(activity!=null){
            activity.clear();
            activity = null;
            System.gc();
        }
        if(broadcastManager!=null){
            broadcastManager.unregister(MQTT_MESSAGE_LISTENER);
        }
        EventBus.getDefault().unregister(this);
    }

    /**
     * 发送mqtt消息
     * @param topic
     * @param message
     */
    public void sendData(String topic,String message){
        MqttService.publish(topic,message);
    }


    /**
     *  订阅主题
     * @param topic
     */
    public void subscribeTopic(String topic){
        MqttService.subscribe(topic);
    }


    /**
     *  取消订阅主题
     * @param topic
     */
    public void unsubscribeTopic(String topic){
        MqttService.unsubscribe(topic);
    }


    private BroadcastManager broadcastManager;


    /**
     *  消息接听
     * @param onDataListener
     */
    public void dataListener(EventDataListener onDataListener){
        if(broadcastManager==null){
            broadcastManager = BroadcastManager.getInstance(activity.get());
        }
        broadcastManager.register(MQTT_MESSAGE_LISTENER, new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String type = intent.getStringExtra("type");
                String topic = intent.getStringExtra("topic");
                String msg = intent.getStringExtra("msg");
                onDataListener.onResult(type, topic, msg);
            }
        });
    }

    /**
     * 取消消息监听
     */
    public void destoryDataListener(){
        broadcastManager.unregister(MQTT_MESSAGE_LISTENER);
    }


    /**
     * 推送异常日志
     * @param pushLog
     */
    public static void pushLog(PushLog pushLog){
        pushLog.setType("java");//java调用的
        CrashPushManager.getInstance().pushLog(pushLog);
    }


    /**
     *  获取系统信息
     * @return
     */
    public SystemConst getConst(){
        int[] screen = CommonUtil.getScreenSize(activity.get());
        SystemConst systemConst = new SystemConst();
        systemConst.setScreenWidth(screen[0]);
        systemConst.setScreenHeight(screen[1]);
        systemConst.setAppName(activity.get().getResources().getString(R.string.app_name));
        systemConst.setAppId(h5AppConfig.getAppKey());
        systemConst.setAppVersion(CommonUtil.getVersionName(activity.get()));
        return systemConst;
    }

    /**
     * 打开新窗口
     * @param param
     */
    public void openWin(WinParam param){
        Intent intent = new Intent(activity.get(), WebActivity.class);
        intent.putExtra("url",param.getUrl());
        intent.putExtra("name",param.getName());
        intent.putExtra("data",param.getData());
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        activity.get().startActivity(intent);
    }

    /**
     * 关闭当前窗口
     */
    public void closeWin(){
        activity.get().finish();
    }

    /**
     * 获取传过来的参数
     */
    public WinParam getWinParam(){
        Intent intent = activity.get().getIntent();
        String data = intent.getStringExtra("data");
        String name = intent.getStringExtra("name");
        String url = intent.getStringExtra("url");
        WinParam winParam = new WinParam();
        winParam.setData(data);
        winParam.setName(name);
        winParam.setUrl(url);
        return winParam;
    }

    /**
     * 结束APP
     */
    public void finishApp(){
        ActivityCollectorUtil.finishAll();
        android.os.Process.killProcess(android.os.Process.myPid());
    }

    /**
     * 重启APP
     */
    public void reloadApp(){
        ActivityCollectorUtil.finishAll();
        Intent intent = new Intent(activity.get(), WebActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
        activity.get().startActivity(intent);
        android.os.Process.killProcess(android.os.Process.myPid());
    }

    /**
     * 设置按返回键可以从当前页返回桌面
     */
    public void setCanBackToMain(boolean canBackToMain){
        this.canBackToMain = canBackToMain;
    }

    /**
     * 跟H5端发送消息
     * @param data
     */
    public void sendEventToWeb(Map<String,Object> data){
        Map<String,Object> map = new HashMap<>();
        map.put("type","JAVA_EVENT");
        map.put("msg", data);
        LogUtil.i("sendEventToWeb",JsonUtil.beanToJson(map));
        BroadcastManager.getInstance(BaseApp.getApp()).sendBroadcast(MQTT_MESSAGE_LISTENER,map);
    }


    /**
     * 网络请求
     * @param param
     * @param ajaxCallback
     * @return
     */
    public String ajax(AjaxParam param, AjaxCallback ajaxCallback){
        if(param!=null){
            RequestCall requestCall;
            String uuid = UUID.randomUUID().toString();
            switch (param.getMethod().toUpperCase()){
                case HttpManager.METHOD
                        .POST:
                    requestCall = HttpManager.post().tag(uuid).url(param.getUrl()).build();
                    break;
                case HttpManager.METHOD.DELETE:
                    requestCall = HttpManager.delete().tag(uuid).url(param.getUrl()).build();
                    break;
                case HttpManager.METHOD.HEAD:
                    requestCall = HttpManager.head().tag(uuid).url(param.getUrl()).build();
                    break;
                case HttpManager.METHOD.OPTION:
                    requestCall = HttpManager.option().tag(uuid).url(param.getUrl()).build();
                    break;
                case HttpManager.METHOD.PATCH:
                    requestCall = HttpManager.patch().tag(uuid).url(param.getUrl()).build();
                    break;
                case HttpManager.METHOD.PUT:
                    requestCall = HttpManager.put().tag(uuid).url(param.getUrl()).build();
                    break;
                case HttpManager.METHOD.TRACE:
                    requestCall = HttpManager.trace().tag(uuid).url(param.getUrl()).build();
                    break;
                default:
                    requestCall = HttpManager.get().tag(uuid).url(param.getUrl()).build();
                    break;
            }

            StringCallback callback = new StringCallback() {
                @Override
                public void onBefore(Request request, int id) {
                    super.onBefore(request, id);
                    AjaxData ajaxData = new AjaxData();
                    ajaxData.setStatus(AjaxData.STATUS_PREVIEW_UPLOAD);
                    ajaxData.setPosition(id);
                    ajaxData.setMsg("开始上传");
                    ajaxCallback.onResult(ajaxData);
                }

                @Override
                public void onAfter(int id) {
                    super.onAfter(id);
                    AjaxData ajaxData = new AjaxData();
                    ajaxData.setStatus(AjaxData.STATUS_UPLOAD_COMPLETE);
                    ajaxData.setPosition(id);
                    ajaxData.setMsg("上传成功");
                    ajaxCallback.onResult(ajaxData);
                }

                @Override
                public void inProgress(float progress, long total, int id) {
                    super.inProgress(progress, total, id);
                    AjaxData ajaxData = new AjaxData();
                    ajaxData.setStatus(AjaxData.STATUS_UPLOADING);
                    ajaxData.setPosition(id);
                    ajaxData.setMsg("上传中...");
                    ajaxData.setProgress(progress);
                    ajaxData.setTotal(total);
                    ajaxCallback.onResult(ajaxData);
                }

                @Override
                public void onError(Call call, Exception e, int id) {
                    AjaxData ajaxData = new AjaxData();
                    ajaxData.setStatus(AjaxData.STATUS_NET_ERROR);
                    ajaxData.setPosition(id);
                    ajaxData.setMsg("请求失败:"+e.getMessage());
                    ajaxCallback.onResult(ajaxData);
                }

                @Override
                public void onResponse(String response, int id) {
                    AjaxData ajaxData = new AjaxData();
                    ajaxData.setStatus(AjaxData.STATUS_ALL_COMPLETE);
                    ajaxData.setPosition(id);
                    ajaxData.setMsg("全部提交");
                    ajaxData.setData(response);
                    LogUtil.e("sdfgsdf", JsonUtil.beanToJson(ajaxData));
                    ajaxCallback.onResult(ajaxData);
                }
            };
            requestCall.execute(callback);
            return requestCall.getRequest().tag().toString();
        }
        return "error";
    }

    /**
     * 取消ajax请求
     * @param tag
     */
    public void cancelAjax(String tag){
        HttpManager.getInstance().cancelTag(tag);
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void update(DownloadInfo info){
        Map<String,Object> map = new HashMap<>();
        map.put("download",info);
        map.put("action","download");
        sendEventToWeb(map);
        //java回调
        if(downloadCallback!=null){
            downloadCallback.onUpdate(info);
        }
    }
    private DownloadCallback downloadCallback;
    /**
     *  断点下载
     * @param url
     * @param
     */
    public void download(String url,DownloadCallback downloadCallback){
        this.downloadCallback = downloadCallback;
        PermissionManager.get(activity.get()).check(
                new String[]{Manifest.permission.READ_EXTERNAL_STORAGE
                ,Manifest.permission.WRITE_EXTERNAL_STORAGE}, () -> {
            DownloadManager.getInstance().download(url);
        });
    }

    /**
     * 暂停下载
     * @param url
     */
    public void pauseDownload(String url){
        DownloadManager.getInstance().pauseDownload(url);
    }

    /**
     * 取消下载
     * @param url
     */
    public void cancelDownload(String url){
        DownloadManager.getInstance().cancelDownload(url);
    }


    /**
     *  读文件
     * @param path
     * @return
     */
    public void readFile(String path, OnResult onResult){
        PermissionManager.get(activity.get()).check(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, () -> {
            String root = FileUtil.getFilePath();;
            TaskManager.getInstance().exec(() -> {
                String txt =  FileUtil.readFile(root+path);
                onResult.onResult(txt);
            });
        });
    }

    /**
     * 写文件
     * @param path
     * @param content
     */
    public void writeFile(String path,String content, OnResult onResult){
        PermissionManager.get(activity.get()).check(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, () -> {
            TaskManager.getInstance().exec(() -> {
                String root = FileUtil.getFilePath();
                 boolean isOk =  FileUtil.saveFile(content,root+path);
                onResult.onResult(isOk+"");
            });
        });
    }

    /**
     * 删除文件
     * @param path
     * @param onResult
     */
    public void delFile(String path, OnResult onResult){
        PermissionManager.get(activity.get()).check(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE
                ,Manifest.permission.WRITE_EXTERNAL_STORAGE}, () -> {
            TaskManager.getInstance().exec(() -> {
                boolean isOk = FileUtil.deleteFile(path);
                onResult.onResult(isOk+"");
            });
        });
    }

    /**
     * 保存键值数据
     * @param key
     * @param value
     * @return
     */
    public boolean putData(String key,Object value){
        return SharedPreferencesUtil.putData(key,value);
    }

    /**
     * 读取键值数据
     * @param key
     * @param defaultValue
     * @param <T>
     * @return
     */
    public <T>T getData(String key,Object defaultValue){
        return (T) SharedPreferencesUtil.getData(key,defaultValue);
    }


    /**
     * 拨打电话
     * @param tel
     */
    public void callTel(String tel){
        PermissionManager.get(activity.get()).check(
                new String[]{Manifest.permission.CALL_PHONE}, () -> {
            CommonUtil.callTel(activity.get(),tel);
        });
    }


    /**
     *  获取定位
     */
    public void getLocation(LocationHelper.OnResult locationCallback){
        PermissionManager.get(activity.get()).check(new String[]{
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION
        }, () -> LocationHelper.getLocation(true,locationCallback));
    }

    /**
     *  显示提示
     * @param msg
     */
    public void showToast(String msg){
        ToastUtil.longToast(activity.get(),msg);
    }

    private int TAKE_PHOEO_BACK = 10203;
    private int GET_PHOTO_BACK = 10294;
    private String takePhotoPath;

    /**
     * 拍照
     */
    public void openCamera(){
        PermissionManager.get(activity.get()).check(new String[]{
                Manifest.permission.CAMERA,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE
        }, () -> takePhotoPath = CommonUtil.takePhoto(activity.get(),TAKE_PHOEO_BACK));
    }

    /**
     * 获取照片
     */
    public void openPhoto(){
        PermissionManager.get(activity.get()).check(new String[]{
                Manifest.permission.READ_EXTERNAL_STORAGE
        }, () ->  CommonUtil.openPhoto(activity.get(),TAKE_PHOEO_BACK));
    }

    private OnPhotoResult onResult;
    public void setOnPhotoResult(OnPhotoResult onResult){
        this.onResult = onResult;
    }
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(resultCode==RESULT_OK){
            if(requestCode== TAKE_PHOEO_BACK){
                if(onResult!=null) {
                    onResult.onPhoto("TAKE_PHOEO",takePhotoPath);
                }
                Map<String,Object> map = new HashMap<>();
                map.put("action","TAKE_PHOEO");
                map.put("path",takePhotoPath);
                sendEventToWeb(map);
            }else if(requestCode==GET_PHOTO_BACK){
                String photoPath = FileUtil.getPhotoPath(activity.get(),data);
                Map<String,Object> map = new HashMap<>();
                map.put("action","GET_PHOEO");
                map.put("path",photoPath);
                sendEventToWeb(map);
                if(onResult!=null) {
                    onResult.onPhoto("GET_PHOEO",photoPath);
                }
            }
        }
    }


    private AudioRecordManager audioRecordManager;

    /**
     *  开启录音
     * @param audioCallback
     * @param time
     */
    public void startRecord(AudioCallback audioCallback,int time){
        PermissionManager.get(activity.get()).check(
                new String[]{
                        Manifest.permission.RECORD_AUDIO,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.READ_EXTERNAL_STORAGE
                }, () -> {
                    audioRecordManager = AudioRecordManager.get(audioCallback,time);
                    audioRecordManager.startRecord();
                });
    }

    /**
     *  暂停或继续
     */
    public void pauseRecord(){
        if(audioRecordManager!=null){
            audioRecordManager.pauseRecord();
        }
    }
    /**
     * 停止录音
     * @param saveAudio
     */
    public void stopRecord(boolean saveAudio){
        if(audioRecordManager!=null){
            audioRecordManager.stopRecord(saveAudio);
        }
    }


    /**
     *  检查更新
     */
    public void checkUpdate(){
        Update.toUpdate(activity.get());
    }

    /**
     * 取消忽略 直接显示出来
     * @param cancelIgnoreVersion
     */
    public void checkUpdate(boolean cancelIgnoreVersion){
        if(cancelIgnoreVersion) {
            UpdateUtils.cancelIgnoreVersion(activity.get());
        }
        checkUpdate();
    }

    /**
     * 获取设备指纹
     * @param onResult
     */
    public void getFingerprint(OnResult onResult){
        TaskManager.getInstance().exec(new Task() {
            @Override
            public Task doTask() {
                String fingerprint = FingerprintUtil.getFingerprint(activity.get());
                setResult(fingerprint);
                return this;
            }
        }, task -> {
            if(onResult!=null){
                onResult.onResult(task.getResult());
            }
        });
    }
}
